package com.mall.user.intercepter;

import com.alibaba.fastjson.JSON;
import com.mall.commons.result.ResponseData;
import com.mall.commons.result.ResponseUtil;
import com.mall.commons.tool.utils.CookieUtil;
import com.mall.user.ILoginService;
import com.mall.user.annotation.Anoymous;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.dto.CheckAuthRequest;
import com.mall.user.dto.CheckAuthResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import sun.rmi.runtime.Log;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 用来实现token拦截认证
 *
 * 其实就是用来判断当前这个操作是否需要登录
 */
public class TokenIntercepter extends HandlerInterceptorAdapter {

//    @Reference(timeout = 3000,check = false)
//    ILoginService iUserLoginService;

    public static String ACCESS_TOKEN="access_token";

    public static String USER_INFO_KEY="userInfo";

    @Reference
    ILoginService iLoginService;

    @Override
    public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {
        //跨域问题
        //设置允许所有跨域访问（⽀持带Cookie）
        response.setHeader("Access-Control-Allow-Origin",
                request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true"); // 配合前端
        response.setHeader("Access-Control-Allow-Methods",
                "POST,GET,PUT,OPTIONS,DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin,XRequested-With,Content-Type,Accept,Authorization,token");

        //1.handler参数表示处理该请求的那个controller的方法
        //2.若handler对象是HandlerMethod类型的对象，说明当前拦截器拦截到的是
        // 一个动态资源请求（非html、jsp等静态资源请求）
        if(!(handler instanceof HandlerMethod)){
            //放行（静态资源请求）
            return true;
        }

        //动态资源请求
        HandlerMethod handlerMethod=(HandlerMethod)handler;
        Object bean=handlerMethod.getBean();
        // 判断（是否为匿名请求：有些请求不需要判断是否登录，如首页则我们给方法或类添加匿名注解）
        if(isAnoymous(handlerMethod)){
            //handler对象表示的方法或该方法所属的controller类上，有匿名注解Anoymous,故返回true
            //放行
            return true;
        }

        //非匿名请求（方法、类上都没有匿名注解），则需要判断是否需要登录
        // 从cookie里面去取token
        String token= CookieUtil.getCookieValue(request,ACCESS_TOKEN);
        if(StringUtils.isEmpty(token)){
            //未携带token
            ResponseData responseData=new ResponseUtil().setErrorMsg("token已失效");
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write(JSON.toJSON(responseData).toString());
            return false;
        }

        //携带token：从token中获取用户信息
        CheckAuthRequest checkAuthRequest=new CheckAuthRequest();
        checkAuthRequest.setToken(token);
        //todo validToken()代码可能欠缺
        CheckAuthResponse checkAuthResponse=iLoginService.validToken(checkAuthRequest);
        if(checkAuthResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())){
            //token验证合格
            //保存token解析后的信息后续要用
            //添加到request域：key-value
            request.setAttribute(USER_INFO_KEY,checkAuthResponse.getUserinfo());
            return super.preHandle(request, response, handler);
        }
        //token验证不合格 通过response响应结果给前端
        ResponseData responseData=new ResponseUtil().setErrorMsg(checkAuthResponse.getMsg());
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write(JSON.toJSON(responseData).toString());

//        CheckAuthResponse checkAuthResponse=iUserLoginService.validToken(checkAuthRequest);
//        if(checkAuthResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())){
//            request.setAttribute(USER_INFO_KEY,checkAuthResponse.getUserinfo()); //保存token解析后的信息后续要用
//            return super.preHandle(request, response, handler);
//        }
//        ResponseData responseData=new ResponseUtil().setErrorMsg(checkAuthResponse.getMsg());
//        response.setContentType("text/html;charset=UTF-8");
//        response.getWriter().write(JSON.toJSON(responseData).toString());
        return false;
    }

    private boolean isAnoymous(HandlerMethod handlerMethod){
        //获取包含该handlerMethod对象所表示的那个方法的controller对象
        Object bean=handlerMethod.getBean();

        //获取controller对象对应的类的Class对象
        Class clazz=bean.getClass();
        //判断Controller的类上有没有骄傲Anoymouus，如果有就返回true,否则返回false
        if(clazz.getAnnotation(Anoymous.class)!=null){
            //类上有匿名注解
            return true;
        }

        //类上没有匿名注解，但若方法上有也返回true,否则返回false
        Method method=handlerMethod.getMethod();
        return method.getAnnotation(Anoymous.class)!=null;
    }
}
